package com.example.music.service.impl;


import com.example.commonutils.R;
import com.example.music.service.DownloadService;
import com.example.music.utils.ConstantPropertiesUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;

/**
 * @ClassName DownloadServicecImpl
 * @Author: wx
 * @Create: 2022-10-08  20:15
 * @Description TODO
 * @Version: 1.0
 **/
@Service
public class DownloadServiceImpl implements DownloadService {
    @Override
    public void downLoadFile(HttpServletRequest request, HttpServletResponse response, String song) {
        //本地字符编码
        String localCharset = ConstantPropertiesUtils.LOCAL_CHARSET;
        // FTP协议里面，规定文件名编码为iso-8859-1
        String serverCharset = ConstantPropertiesUtils.SERVER_CHARSET;
        // ip地址
        String host = ConstantPropertiesUtils.HOST;
        // 端口
        int port = ConstantPropertiesUtils.PORT;
        // ftp用户名
        String username = ConstantPropertiesUtils.USERNAME;
        // ftp用户密码
        String password = ConstantPropertiesUtils.PASSWORD;
        //文件在服务器端保存的主目录
        int i = song.lastIndexOf("/");
        String src = song.substring(0, i + 1);
        //文件名称
        String name = song.substring(i + 1, song.length());
        System.out.println(name);
        response.setCharacterEncoding(localCharset);
        InputStream is = null;
        OutputStream os = null;
        FTPClient ftp = new FTPClient();
        try {
            int reply;
            // 连接FTP服务器
            ftp.connect(host, port);
            // 如果采用默认端口，可以使用ftp.connect(host)的方式直接连接FTP服务器  登录
            ftp.login(username, password);
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                //return R.error("ftp链接失败，请联系管理员");
            }
            //切换到上传目录
            ftp.changeWorkingDirectory(src);
            //读取所有文件
            FTPFile[] fs = ftp.listFiles();
            //设置上传文件的类型为二进制类型
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            for (FTPFile ff : fs) {
                String filename = new String(ff.getName().getBytes("iso-8859-1"), "UTF-8");
                if (name.equals(filename)) {
                    //is = ftp.retrieveFileStream(new String(name.getBytes("UTF-8"), "iso-8859-1"));
                    //分片下载，获取文件长度
                    long fSize = ff.getSize();
                    //设置相应类型
                    response.setContentType("application/x-download");
                    //打开下载框
                    response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(name,localCharset));
                    //http 传Range Range 的 value 是bytes=     表示可以分片下载
                    //后台响应前端支持分配分片下载
                    response.setHeader("Accept-Range", "bytes");

                    response.setHeader("fSize", String.valueOf(fSize));
                    response.setHeader("fName", URLEncoder.encode(name,localCharset));
                    //记录开始起始切片位置
                    long pos = 0;
                    //结束位置
                    long last = fSize - 1;
                    //总共读了多少
                    long sum = 0;
                    if (null != request.getHeader("Range")) {
                        //状态码  206  就是在分片下载
                        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                        String numRange = request.getHeader("Range").replaceAll("bytes=", "");
                        String[] strRange = numRange.split("-");
                        if (strRange.length == 2) {
                            pos = Long.parseLong(strRange[0].trim());
                            last = Long.parseLong(strRange[1].trim());
                            if (last > fSize - 1) {
                                last = fSize - 1;
                            }
                        } else {
                            pos = Long.parseLong(numRange.replaceAll("-", "").trim());
                        }
                    }
                    long rangeLength = last - pos + 1;
                    String contentRange = new StringBuffer("bytes").append(pos).append("-").append(last).append("/").append(fSize).toString();
                    response.setHeader("content-Range", contentRange);
                    response.setHeader("content-Length", rangeLength + "");
                    os = new BufferedOutputStream(response.getOutputStream());
                    is = ftp.retrieveFileStream(new String(name.getBytes("UTF-8"), "iso-8859-1"));
                    is.skip(pos);

                    byte[] bytes = new byte[1024*1024*10];
                    int length = 0;
                    while (sum < rangeLength) {
                        int l = (int)(rangeLength - sum) <= bytes.length ? (int)(rangeLength - sum) : bytes.length;
                        length = is.read(bytes, 0, l);
                        sum += length;
                        os.write(bytes,0,length);
                    }
                    //System.out.println("下载完成");
                    break;
                }

            }
            ftp.logout();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //return R.success("下载成功");
    }

    @Override
    public String downloadSong(String song) {
        //本地字符编码
        String localCharset = ConstantPropertiesUtils.LOCAL_CHARSET;
        // FTP协议里面，规定文件名编码为iso-8859-1
        String serverCharset = ConstantPropertiesUtils.SERVER_CHARSET;
        // ip地址
        String host = ConstantPropertiesUtils.HOST;
        // 端口
        int port = ConstantPropertiesUtils.PORT;
        // ftp用户名
        String username = ConstantPropertiesUtils.USERNAME;
        // ftp用户密码
        String password = ConstantPropertiesUtils.PASSWORD;
        //文件在服务器端保存的主目录
        int i = song.lastIndexOf("/");
        String src = song.substring(0, i + 1);
        //文件名称
        String name = song.substring(i + 1, song.length());

        boolean result = false;
        FTPClient ftp = new FTPClient();
        String strBin="";
        try {
            int reply;
            // 连接FTP服务器
            ftp.connect(host, port);
            // 如果采用默认端口，可以使用ftp.connect(host)的方式直接连接FTP服务器  登录
            ftp.login(username, password);
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return "登陆失败";
            }
            //切换到上传目录
            ftp.changeWorkingDirectory(src);
            //读取所有文件
            FTPFile[] fs = ftp.listFiles();
            //设置上传文件的类型为二进制类型
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            for (FTPFile ff : fs) {
                String filename = new String(ff.getName().getBytes("iso-8859-1"), "UTF-8");
                if (name.equals(filename)){
                    InputStream is = ftp.retrieveFileStream(new String(name.getBytes("UTF-8"), "iso-8859-1"));
                    byte[] bytes = FileCopyUtils.copyToByteArray(is);
                    strBin = new String(bytes,"ISO-8859-1");
                    is.close();
                    break;
                }

            }
            ftp.logout();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
        return strBin;
    }
}
